package com.example.springbootelasticsearch.uitl;

import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
public class ElasticSearchUtil {

    @Resource(name = "restHighLevelClient")
    private RestHighLevelClient client;

    /**
     * 创建索引
     *
     * @param index 索引名称
     * @return
     * @throws IOException
     */
    public CreateIndexResponse createIndex(String index) throws IOException {
        CreateIndexRequest request = new CreateIndexRequest(index);
        CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
        return response;
    }

    /**
     * 删除索引
     *
     * @param index 索引名称
     * @return
     * @throws IOException
     */
    public boolean deleteIndex(String index) throws IOException {
        DeleteIndexRequest request = new DeleteIndexRequest(index);
        boolean existIndex = existIndex(index);
        if (!existIndex) {
            return false;
        }
        AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
        return response.isAcknowledged();
    }

    /**
     * 是否存在索引
     *
     * @param index 索引名称
     * @return
     * @throws IOException
     */
    public boolean existIndex(String index) throws IOException {
        GetIndexRequest request = new GetIndexRequest(index);
        return client.indices().exists(request, RequestOptions.DEFAULT);
    }


// ============================对索引中的记录的操作=============================

    /**
     * 向指定索引中插入一条记录
     *
     * @param index  索引名称
     * @param object 记录值
     * @return
     * @throws IOException
     */
    public RestStatus insertDoc(String index, Object object) throws IOException {
        IndexRequest request = new IndexRequest(index);
        request.source(JSON.toJSONString(object), XContentType.JSON);
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);
        return response.status();
    }

    /**
     * 给指定索引批量插入多条记录
     *
     * @param index 索引名称
     * @param list  记录集合
     * @return
     * @throws IOException
     */
    public RestStatus bulkDoc(String index, List<Object> list) throws IOException {
        BulkRequest request = new BulkRequest();
        for (int i = 0; i < list.size(); i++) {
            request.add(new IndexRequest(index).source(JSON.toJSONString(list.get(i)), XContentType.JSON));
        }
        BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
        return response.status();
    }

    /**
     * 查询索引中的记录
     *
     * @param keyword  搜索关键字
     * @param index    索引名称
     * @param property 要搜索的列值
     * @param pageNo   页码
     * @param pageSize 页的大小
     * @throws IOException
     */
    public  List<Map<String, Object>> search(String index, String keyword, String property, int pageNo, int pageSize) throws IOException {
        if (pageNo < 0) {
            pageNo = 0;
        }
        SearchRequest request = new SearchRequest(index);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        //分页查询,注意查询出来的第一条记录的下标是从0开始的
        builder.from(pageNo);
        builder.size(pageSize);
        //分词查询
        MatchQueryBuilder matchBuilder = QueryBuilders.matchQuery(property, keyword).analyzer("standard");
        builder.query(matchBuilder);
        //执行查询
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //每个list里面的每个map都是一条记录
        List<Map<String, Object>> list = new ArrayList<>();
        for (SearchHit field : response.getHits().getHits()) {
            list.add(field.getSourceAsMap());
        }
        return list;
    }

    /**
     * 获取指定索引中的某一条记录，注意docIndex是随机生成的
     *
     * @param index    索引名称
     * @param docIndex 记录的位置
     * @return
     * @throws IOException
     */
    public String getDoc(String index, String docIndex) throws IOException {
        GetRequest request = new GetRequest(index, docIndex);
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        return response.getSourceAsString();
    }


    /**
     * 更新指定索引中的某条记录，注意docIndex是随机生成的
     *
     * @param index    索引名称
     * @param docIndex 记录的位置
     * @param value    新的记录值
     * @return
     * @throws IOException
     */
    public RestStatus updDoc(String index, String docIndex, Object value) throws IOException {
        UpdateRequest request = new UpdateRequest(index, docIndex);
        request.doc(JSON.toJSONString(value), XContentType.JSON);
        UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
        return response.status();
    }

    /**
     * 删除指定索引下的某条记录，注意docIndex是随机生成的
     *
     * @param index    索引名称
     * @param docIndex 索引的位置
     * @return
     * @throws IOException
     */
    public RestStatus delDoc(String index, String docIndex) throws IOException {
        DeleteRequest request = new DeleteRequest(index, docIndex);
        DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
        return response.status();
    }

}
